package com.yuanli.card.manage.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yuanli.card.exception.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by layne on 2018/12/7.
 */
public class ChannelInterfaceHelper {

    private static Logger logger = LoggerFactory.getLogger(ChannelInterfaceHelper.class);

    private static volatile Map<String, ChannelInterface> data;

    private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    static {//延迟初始化
        load();
    }

    /**
     * 当Load方法被调用时 getAbility方法阻塞
     *
     * @throws IOException
     */
    public static void load() {
        readWriteLock.writeLock().lock();
        InputStream stream = null;
        try {
            logger.info("加载接口配置数据...");
            data = new HashMap<>();
            ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();

            if (stream == null) {
                stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("channelInterface.json");
            }
            TypeReference<List<ChannelInterface>> reference = new TypeReference<List<ChannelInterface>>() {
            };

            List<ChannelInterface> channelInterfaces = null;
            try {
                channelInterfaces = objectMapper.readValue(stream, reference);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (channelInterfaces != null) {
                channelInterfaces.stream()
                        .forEach(channelInterface -> data.put(channelInterface.getChannelName(), channelInterface));
            }
            logger.info("接口配置数据加载完毕...");
        } finally {
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            readWriteLock.writeLock().unlock();
        }
    }

    public static ChannelInterface.AbilitiesBean.AbilityBean getAbility(String channelNo, String abilityName) {
        readWriteLock.readLock().lock();
        try {
            if (data == null || data.size() == 0) {
                logger.warn("配置未加载");
                throw new ServiceException(999, "配置未加载");
            }

            ChannelInterface channelInterface = Optional.ofNullable(data.get(channelNo))
                    .orElseThrow(() -> new ServiceException(999, "通道未配置"));

            ChannelInterface.AbilitiesBean abilitiesBean = channelInterface.getAbilities()
                    .parallelStream()
                    .filter(abilitiesBean1 -> abilitiesBean1.getAbilityName().equals(abilityName))
                    .findAny()
                    .orElseThrow(() -> new ServiceException(999, "未获取到通道能力"));
            ChannelInterface.AbilitiesBean.AbilityBean ability = abilitiesBean.getAbility();
            return ability;
        } finally {
            readWriteLock.readLock().unlock();
        }

    }
}
